package ecom.beans;

import ecom.beans.dao.ProductDAO;
import ecom.beans.dao.ProductstoreDAO;
import ecom.beans.dao.StockDAO;
import ecom.beans.dao.TransactionDAO;
import ecom.beans.exception.AccountBeanException;
import ecom.beans.exception.CartException;
import ecom.beans.exception.StockQuantityUnavailable;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.ejb.Stateful;

@Stateful
public class CartBean implements CartLocal, Serializable {

    private CartState state;
    private static Set<PurchaseBean> cart;

    public enum CartState {

        EMPTY,
        FILLING,
        BOUGHT
    };

    @Override
    public CartState getState() {
        return state;
    }

    @Override
    public void setState(CartState state) {
        this.state = state;
    }

    @Override
    public void addProduct(AccountBean account, Long idProduct, Long idProductstore, Integer quantity) throws CartException, StockQuantityUnavailable {
        if (state == CartState.BOUGHT) {
            throw new CartException("The purchase of the cart has already been done");
        } else {
            ProductBean product = ProductDAO.getByIdProduct(idProduct);
            ProductstoreBean productstore = ProductstoreDAO.getByIdProductstore(idProductstore);
            StockBean stock = StockDAO.getByIdProductstoreAndIdProduct(idProduct, idProductstore);
            PurchaseBean purchase = new PurchaseBean(account, productstore, product, quantity, stock.getPrice());
            if (purchase.getQuantity() > stock.getQuantity()) {
                throw new StockQuantityUnavailable("The quantity asked is not available in the stock of the producstore");
            }
            if (findPurchase(idProductstore, idProduct) != null) {
                PurchaseBean purchaseFound = findPurchase(idProductstore, idProduct);
                purchaseFound.setQuantity(purchaseFound.getQuantity() + quantity);
                purchaseFound.setPrice(stock.getPrice());
            } else {
                cart.add(purchase);
            }
            if (state == CartState.EMPTY) {
                state = CartState.FILLING;
            }

        }
    }

    @Override
    public void updateProductQuantity(Long idProduct, Long idProductstore, Integer quantity) throws StockQuantityUnavailable, CartException {
        if (state == CartState.BOUGHT) {
            throw new CartException("The purchase of the cart has already been done");
        } else {
            if (findPurchase(idProductstore, idProduct) != null) {
                PurchaseBean found = findPurchase(idProductstore, idProduct);
                if (quantity == 0) {
                    cart.remove(found);
                } else {
                    StockBean stock = StockDAO.getByIdProductstoreAndIdProduct(idProduct, idProductstore);
                    if (quantity > stock.getQuantity()) {
                        throw new StockQuantityUnavailable("The quantity asked is not available in the stock of the producstore");
                    } else {
                        found.setQuantity(quantity);
                    }
                }
                if (cart.isEmpty()) {
                    this.setState(CartState.EMPTY);
                }
            } else {
                throw new CartException("The product " + idProduct + " in the productstore " + idProductstore + " is not in the cart");
            }
        }
    }

    @Override
    public void removeProduct(Long idProduct, Long idProductstore) throws CartException {
        if (state == CartState.BOUGHT) {
            throw new CartException("The purchase of the cart has already been done");
        } else {
            PurchaseBean found = findPurchase(idProductstore, idProduct);
            if (found != null) {
                cart.remove(found);
            } else {
                throw new CartException("The product " + idProduct + " in the productstore " + idProductstore + " is not in the cart");
            }
            if (cart.isEmpty()) {
                this.setState(CartState.EMPTY);
            }
        }
    }

    private PurchaseBean findPurchase(Long idProductstore, Long idProduct) {
        PurchaseBean obj = null;
        PurchaseBean result = null;
        Iterator<PurchaseBean> it = cart.iterator();
        while (it.hasNext()) {
            obj = it.next();
            if (obj.getProductstoreBean().getIdProductStore().equals(idProductstore) && obj.getProductBean().getIdProduct().equals(idProduct)) {
                result = obj;
            }
        }
        return result;
    }

    @Override
    public Set<PurchaseBean> getCart() {
        return cart;
    }

    @Override
    public Double getTotalPrice() {
        double totalPrice = 0;
        if (cart != null) {
            Iterator<PurchaseBean> it = cart.iterator();
            while (it.hasNext()) {
                PurchaseBean purchase = it.next();
                totalPrice = totalPrice + purchase.getPrice() * purchase.getQuantity();
            }
        }
        return totalPrice;
    }

    @Override
    public void buy(AccountBean account) throws CartException, AccountBeanException {
        List obj = new ArrayList();
        List delObj = new ArrayList();
        if (state == CartState.EMPTY) {
            throw new CartException("Le content of your cart is empty");
        } else if (state == CartState.BOUGHT) {
            throw new CartException("The purchase of the cart has already been done");
        } else {
            try {
                account.withdraw(getTotalPrice());
            } catch (AccountBeanException e) {
                throw new AccountBeanException("Your account balance is not suffisant");
            }
            obj.add(account);
            Iterator<PurchaseBean> it = cart.iterator();
            PurchaseBean purchase = null;
            while (it.hasNext()) {
                purchase = it.next();
                StockBean stockCorrespondant = StockDAO.getByIdProductstoreAndIdProduct(purchase.purchaseBeanPK.getIdProduct(),
                        purchase.purchaseBeanPK.getIdProductStore());
                if ((stockCorrespondant.getQuantity() - purchase.getQuantity()) == 0) {
                    delObj.add(stockCorrespondant);
                } else {
                    stockCorrespondant.setQuantity(stockCorrespondant.getQuantity() - purchase.getQuantity());
                }
                obj.add(purchase);
                obj.add(stockCorrespondant);
            }
            try {
                TransactionDAO.saveOrUpdateAllObjects(obj);
                TransactionDAO.deleteAllObjects(delObj);
                emptyCart();
            } catch (Exception e) {
                e.printStackTrace(System.err);
            }

        }
    }

    @Override
    public void emptyCart() {
        cart.clear();
        setState(CartState.EMPTY);
    }

    @Override
    public void initializeCart() {
        cart = new HashSet<PurchaseBean>();
    }
}
